iT邦幫忙

2023 iThome 鐵人賽

DAY 24
0

目前的網站上只有 Articles(文章)作為發文類型,但既然要建置的是 Digital Garden,我也希望讓發文類型能擴及Notes、Literatures 與 MoC 這幾種類別,我是這樣定義他們的:

  • Articles:我所發表的正式文章,通常會是數個 Note 集結而成且具脈絡性與結構的文體。
  • Notes:我對某個概念的詮釋,一則 Note 只會有一個觀念或者只講一件事。
  • Literatures:我閱讀某篇文章、看了某部影片等學習途徑的一些速記,這些速記會在日後拆解成一則則的 Note。
  • MoC:用來取代傳統 Blog 的 Category 功能,我會依照某些主題,建立與之相關的 Articles、Notes、Literatures,並會有一定的順序與參照結構。

事實上這些發文類型在頁面和元件的程式碼幾乎是一致的,不同的地方只有在做查詢檔案的路徑不同。我預計他們存放的路徑會是

- @
  - components
    - ListPage.vue
    - PostPage.vue
  - content
    - articles
      - [...slug].vue
      - index.vue
    - notes
      - [...slug].vue
      - index.vue
    - literatures
      - [...slug].vue
      - index.vue
    - moc
      - [...slug].vue
      - index.vue
  - pages
    - ....

我只要把原本 @/articles/index.vue 的檔案內容除了查詢方法外抽出成 @components/ListPage.vue,並把 @/articles/[...slug].vue 抽成 @components/PostPage.vue,並且讓其他頁面的 index.vue[...slug].vue 分別引用,就完成了。

各發文類型的 @/pages/post-type/index.vue

<template>
  <ContentDoc v-slot="{ doc }">
    <PostPage :post="(doc as Post)" />
  </ContentDoc>
</template>
<script setup lang="ts">
import { Post } from '@/types/index'
</script>

與之相關的 @components/PostPage.vue

<template>
  <article class="pb-4">
     <PostHeader :post="post"/>
     <PostContent :post="post"/>
     <PostFooter :post="post"/>
   </article>
</template>
<script setup lang="ts">
import { Post } from '@/types/index'

defineProps<{
 post: Post
}>()
</script>

各發文類型的 @/pages/post-type/[...slug].vue

<template>
  <ListPage />
</template>

與之相關的 @components/ListPage.vue

<template>
  <section class="pb-24">
    <div class="divide-y divide-gray-200">
      <header class="pb-8 space-y-2 md:space-y-5">
        <div>
          <h1 class="tracking-tight font-extrabold text-gray-900 text-2xl leading-6 mb-1">
            {{ slug.toUpperCase }}
          </h1>
        </div>
        <SearchBar v-model="searchValue" placeholder-text="Search announce" />
      </header>
      <main>
        <ul>
          <li v-for="article in filteredArticles" :key="article._path" class="py-4">
            <ListItem :item="article" />
          </li>
        </ul>
      </main>
    </div>
  </section>
</template>
<script lang="ts" setup>
import { Post } from '@/types/index'
import { DateTime } from 'luxon';

const route = useRoute()
const slug = route.fullPath
const posts = [] // 各發文類型的查詢函式

const searchValue = ref('')

const { data } = await useAsyncData(slug, () =>
  queryContent(slug)
    .where({ slug: { $ne: slug }, _file: { $not: { $contains: 'index' } } })
    .sort({ created_at: -1, published_at: -1 })
    .find()
)
const post = data.value as Post[]

const articles = post.map((post) => {
  const hasPostTags = !!post.tags
  if (!hasPostTags) {
    post.tags = []
  }
  return post
})

const filteredArticles = computed(() => {
  return articles.filter((post: Post) => {
    const tags = post.tags.filter((tag) => !!tag)
    const searchContent =
      post.title +
      tags.map((tag: string) => (tag ? tag.split(' ').join('-') : '')) +
      DateTime.fromISO(post.published_at).toFormat('yyyy-LL-dd')
    return searchContent.toLowerCase().includes(searchValue.value.toLowerCase())
  })
})
</script>

最後再去修改 @/compoents/TheHeader.vue 中的導覽列連結,加入這些新發文類型清單的連結,就算大功告成啦!


上一篇
透過外掛實作文章自訂網址功能
下一篇
增加關燈模式,讓閱讀更加護眼
系列文
用 Nuxt Content 搭配 Obsidian 建立自己的 Digital Garden30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言